open Core_kernel.Std
open Semantics

type ast_endpoint = {
  ep_path : path;
  ep_range : (int * int) option;
}

let string_of_ast_endpoint ep =
  let path_s = (String.concat ~sep:"." ep.ep_path) in
  match ep.ep_range with
  | Some (lo, hi) ->
      Printf.sprintf "%s[%d:%d]" path_s (hi-1) lo
  | None -> path_s

type ast_driver =
  | Ast_driver_var of ast_endpoint
  | Ast_driver_const of int * int

type ast_wire = ast_driver * ast_endpoint
type ast_labeled_wire = ast_driver * ast_endpoint * string list option
type ast_datapath = ast_driver * ast_endpoint * string list option (* labels *)

(* instance_name, (type_name, params) *)
type ast_blackbox = string * (string * (string * int) list)

type ast_stage = {
  mutable stage_ports : (string * Vlog.port) list;
  mutable stage_modules : ast_blackbox list;
  mutable stage_wires : ast_labeled_wire list;
  stage_feedback_wires_opt : ast_datapath list option;
}

type toplevel = {
  mutable top_ports : (string * Vlog.port) list;
  mutable top_modules : ast_blackbox list;
  mutable top_wires : ast_wire list;
  mutable top_pipeline : string list;
  mutable top_stages : (string * ast_stage) list;
  mutable top_paths : ast_datapath list;
  mutable top_encodings : string list;
}

let empty_toplevel : toplevel = {
  top_ports = [];
  top_modules = [];
  top_wires = [];
  top_pipeline = [];
  top_stages = [];
  top_paths = [];
  top_encodings = [];
}
